import os
import re
import tempfile
import subprocess
from typing import Dict, Any
from docx import Document
from docx.shared import Inches, Pt
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.enum.style import WD_STYLE_TYPE
import markdown
from markdown.extensions import tables, codehilite, toc
import logging

logger = logging.getLogger(__name__)

class MarkdownConverter:
    """Markdown转换器"""
    
    def to_docx(self, markdown_content: str, output_path: str, options: Dict[str, Any] = None):
        """
        将Markdown转换为Word文档
        
        Args:
            markdown_content: Markdown内容
            output_path: 输出Word文档路径
            options: 转换选项
        """
        if not options:
            options = {}
        
        doc = Document()
        
        # 设置文档样式
        self._setup_document_styles(doc)
        
        # 解析Markdown内容
        lines = markdown_content.split('\n')
        i = 0
        
        while i < len(lines):
            line = lines[i].strip()
            
            if not line:
                i += 1
                continue
            
            # 处理标题
            if line.startswith('#'):
                self._add_heading(doc, line)
            
            # 处理表格
            elif '|' in line and self._is_table_row(line):
                table_lines = []
                while i < len(lines) and ('|' in lines[i] or lines[i].strip() == ''):
                    if lines[i].strip():
                        table_lines.append(lines[i])
                    i += 1
                i -= 1  # 回退一行
                self._add_table(doc, table_lines)
            
            # 处理代码块
            elif line.startswith('```'):
                code_lines = []
                i += 1
                while i < len(lines) and not lines[i].strip().startswith('```'):
                    code_lines.append(lines[i])
                    i += 1
                self._add_code_block(doc, '\n'.join(code_lines))
            
            # 处理列表
            elif line.startswith(('- ', '* ', '+ ')) or re.match(r'^\d+\. ', line):
                list_lines = []
                while i < len(lines) and (lines[i].strip().startswith(('- ', '* ', '+ ')) or 
                                        re.match(r'^\d+\. ', lines[i].strip()) or 
                                        lines[i].strip() == ''):
                    if lines[i].strip():
                        list_lines.append(lines[i])
                    i += 1
                i -= 1
                self._add_list(doc, list_lines)
            
            # 处理普通段落
            else:
                self._add_paragraph(doc, line, options)
            
            i += 1
        
        # 保存文档
        doc.save(output_path)
    
    def to_pdf(self, markdown_content: str, output_path: str, options: Dict[str, Any] = None):
        """
        将Markdown转换为PDF
        
        Args:
            markdown_content: Markdown内容
            output_path: 输出PDF路径
            options: 转换选项
        """
        try:
            # 先转换为HTML
            html_content = self._markdown_to_html(markdown_content, options)
            
            # 创建临时HTML文件
            with tempfile.NamedTemporaryFile(mode='w', suffix='.html', delete=False, encoding='utf-8') as f:
                f.write(html_content)
                temp_html = f.name
            
            try:
                # 使用wkhtmltopdf转换为PDF
                cmd = [
                    'wkhtmltopdf',
                    '--page-size', 'A4',
                    '--margin-top', '0.75in',
                    '--margin-right', '0.75in',
                    '--margin-bottom', '0.75in',
                    '--margin-left', '0.75in',
                    '--encoding', 'UTF-8',
                    temp_html,
                    output_path
                ]
                
                result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
                
                if result.returncode != 0:
                    raise Exception(f"wkhtmltopdf转换失败: {result.stderr}")
                    
            finally:
                # 清理临时文件
                os.unlink(temp_html)
                
        except FileNotFoundError:
            # 如果没有wkhtmltopdf，尝试使用其他方法
            try:
                import pdfkit
                html_content = self._markdown_to_html(markdown_content, options)
                pdfkit.from_string(html_content, output_path)
            except ImportError:
                raise Exception("需要安装wkhtmltopdf或pdfkit库来支持Markdown转PDF")
    
    def _setup_document_styles(self, doc):
        """设置文档样式"""
        styles = doc.styles
        
        # 设置正文样式
        normal_style = styles['Normal']
        normal_font = normal_style.font
        normal_font.name = '微软雅黑'
        normal_font.size = Pt(12)
        
        # 设置标题样式
        for i in range(1, 7):
            heading_style_name = f'Heading {i}'
            if heading_style_name in styles:
                heading_style = styles[heading_style_name]
                heading_font = heading_style.font
                heading_font.name = '微软雅黑'
                heading_font.size = Pt(18 - i * 2)
    
    def _add_heading(self, doc, line):
        """添加标题"""
        level = len(line) - len(line.lstrip('#'))
        text = line.lstrip('#').strip()
        
        if level <= 6:
            doc.add_heading(text, level)
        else:
            # 超过6级的标题作为普通段落处理
            p = doc.add_paragraph()
            run = p.add_run(text)
            run.bold = True
    
    def _add_paragraph(self, doc, text, options):
        """添加段落"""
        # 处理内联格式
        formatted_text = self._process_inline_formatting(text)
        
        p = doc.add_paragraph()
        self._add_formatted_text(p, formatted_text)
    
    def _add_table(self, doc, table_lines):
        """添加表格"""
        if len(table_lines) < 2:
            return
        
        # 解析表格数据
        rows = []
        for line in table_lines:
            if '---' in line:  # 跳过分隔行
                continue
            cells = [cell.strip() for cell in line.split('|')[1:-1]]  # 去掉首尾空元素
            if cells:
                rows.append(cells)
        
        if not rows:
            return
        
        # 创建表格
        table = doc.add_table(rows=len(rows), cols=len(rows[0]))
        table.style = 'Table Grid'
        
        # 填充表格数据
        for i, row_data in enumerate(rows):
            row = table.rows[i]
            for j, cell_data in enumerate(row_data):
                if j < len(row.cells):
                    row.cells[j].text = cell_data
    
    def _add_code_block(self, doc, code):
        """添加代码块"""
        p = doc.add_paragraph()
        run = p.add_run(code)
        run.font.name = 'Consolas'
        run.font.size = Pt(10)
        
        # 设置段落样式
        p.style = doc.styles['Normal']
    
    def _add_list(self, doc, list_lines):
        """添加列表"""
        for line in list_lines:
            line = line.strip()
            if line.startswith(('- ', '* ', '+ ')):
                # 无序列表
                text = line[2:].strip()
                p = doc.add_paragraph(text, style='List Bullet')
            elif re.match(r'^\d+\. ', line):
                # 有序列表
                text = re.sub(r'^\d+\. ', '', line).strip()
                p = doc.add_paragraph(text, style='List Number')
    
    def _process_inline_formatting(self, text):
        """处理内联格式"""
        # 这里简化处理，实际应该用更复杂的解析器
        return text
    
    def _add_formatted_text(self, paragraph, text):
        """添加格式化文本"""
        # 简化实现，直接添加文本
        paragraph.add_run(text)
    
    def _is_table_row(self, line):
        """判断是否为表格行"""
        return line.count('|') >= 2
    
    def _markdown_to_html(self, markdown_content, options):
        """将Markdown转换为HTML"""
        # 配置Markdown扩展
        extensions = ['tables', 'codehilite', 'toc', 'fenced_code']
        
        md = markdown.Markdown(extensions=extensions)
        html_body = md.convert(markdown_content)
        
        # 创建完整的HTML文档
        html_template = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
            <title>Converted Document</title>
            <style>
                body {{
                    font-family: 'Microsoft YaHei', Arial, sans-serif;
                    line-height: 1.6;
                    margin: 40px;
                }}
                table {{
                    border-collapse: collapse;
                    width: 100%;
                    margin: 20px 0;
                }}
                th, td {{
                    border: 1px solid #ddd;
                    padding: 8px;
                    text-align: left;
                }}
                th {{
                    background-color: #f2f2f2;
                }}
                code {{
                    background-color: #f4f4f4;
                    padding: 2px 4px;
                    border-radius: 3px;
                }}
                pre {{
                    background-color: #f4f4f4;
                    padding: 10px;
                    border-radius: 5px;
                    overflow-x: auto;
                }}
            </style>
        </head>
        <body>
            {html_body}
        </body>
        </html>
        """
        
        return html_template 